package study.JavaBase;

import java.io.*;
import java.util.Arrays;

/**
 * date:2025.10.12
 * title:java流，文件，IO
 */

//javaio包用于1.系统的输入输出 2.处理数据流，3.文字读写，4.序列化
//读取数据---输入流，写入数据--输出流
//文件和目录路径名的抽象表示
//文件和目录可以通过file封装城对象，其实封装的并不是一个
//真正存在的文件，是一个路径
public class Java_15 {
    public static void main(String[] arg) {
        try {
//            JavaBase.readConsole.readFunTest();
//            JavaBase.readConsole.readLineTest();
//            JavaBase.FileDealClass.FileInputTest();
//            JavaBase.FileDealClass.FileOutputTest();
//            JavaBase.FileDealClass.myFileOperationTest();
//            FileOperationClass.FileOperationTest();
//            FileTest.createTest();
//            FileIoClass.FileWriteTest();
//            FileIoClass.FileReadTest();
//            FileIoClass.copyAndPaste();
//            FileIoClass.copyVideoManager();
//            FileIoClass.byteBuffer();
//            FileTest.fileManager();
            FileIoClass.byteStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
//        JavaBase.readConsole.writeTest();
//        JavaBase.FileOperationClass.fileList();
//        FileTest.createFileInS();
//        FileManagerDemo.FileManager("D:\\test");

    }

}

//File

class FileTest {
    //File构造方法
    /*
    1.File(String pathName):通过指定的路径名字符串获取file实例
    2.File(String pathName,String Child):从俘虏精美和子路径名创建File实例
    3.File(File fileName,String child):由父路径实例，和子路径获取File实例
     */
    static void createFileInS() {
        String fileName = "D:\\test\\dddd.txt";
        File file = new File(fileName);
        System.out.println(file);
        File file2 = new File("D:\\test", "dddd.txt");
        System.out.println(file);
        File file3 = new File("D:\\test");
        File file4 = new File(file3, "dddd.txt");
        System.out.println(file);
        System.out.println(file2);
        System.out.println(file4);
    }

    /*
    创建功能
    public boolean createNewFile()：创建一个该抽象路径命名的新空文件,文件不存在就创建，返回true，不存在返回false
    public boolean mkdir():创建一级目录,目录不存在就创建，返回true，不存在返回false
    public boolean mkdirs():创建多级目录
    不能用路径名来判断创建的文件类型，看使用的什么方法
     */
    static void createTest() throws IOException {
        File file = new File("D:\\test\\createNewFile.txt");
        file.createNewFile();
        File file2 = new File("D:\\test\\mkdir");
        file2.mkdir();
        File file3 = new File("D:\\test\\mkdirs\\mkdirs1");
        file3.mkdirs();
    }

    //File类判断获取功能
    static void fileManager() throws IOException {
        File file = new File("D:\\test");
        //public boolean isDirectory():测试此抽象路径表示的File是否为目录
        //public boolean isFile():测试此抽象路径名是否为文件
        //public boolean exists():测试file是否存在
        System.out.println("isDirectoty:" + file.isDirectory());
        System.out.println("isFile:" + file.isFile());
        System.out.println("exists:" + file.exists());
        //public String getAbsolutePath(),返回抽象路径的绝对路径字符串
        //public String getPath(),将此抽象路径转为路径字符串
        //public String getName(),返回此抽象路径名表示的文件或者目录的名称
        System.out.println("getAbsoluteFile:" + file.getAbsoluteFile());
        System.out.println("getPath:" + file.getPath());
        System.out.println("getName:" + file.getName());
        //public String[] list(),:返回此抽象路径表示的目录中的字符串数组
        //public File[] listFiles():返回抽象file数组
        String[] fileNameList = file.list();
        File[] files = file.listFiles();
        for (String fileName : fileNameList) {
            System.out.println(fileName + "--->");
        }
        for (File file1 : files) {
            if (file1.isFile()) {
                System.out.println("文件名：" + file1.getName());
            }
        }

        File newFile = new File(file, "create");
        newFile.createNewFile();
        //删除文件
        newFile.delete();
        File newFile2 = new File(file, "Mkdir22\\Mkdir333");
        File newText = new File(newFile2, "test.txt");
        newText.createNewFile();
        newFile2.mkdirs();
        newText.delete();
        newFile2.delete();
    }
}
//读取控制台输出
//java的控制台输入由System.in完成，可以把包装在一个bufferReader对象创建一个字符流
//读取的语法 int read() throw IOException

class readConsole {
    //下面的程序为从控制台不断读取，直到输入c
    static void readFunTest() throws IOException {
        char c;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        do {
            char readChar = (char) br.read();
            c = readChar;
        } while (c != 'c');
    }

    //同上，只不过输入字符串
    static void readLineTest() throws IOException {
        String str = "";
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        do {
            String str1 = (String) br.readLine();
            str = str1;
            //这里怎么可以用 == 号呢？string
        } while (!str.equals("end"));
    }

    static void writeTest() {
        char B = 'A';
        System.out.write(B);
        System.out.println('/');
    }
}

//读写文件
//字节流和字符流
//字节流：用来处理二进制数据，如文件，图像，视频等等
//字符流：用于处理文本数据，比如读写字符串
//可以用字符串类型的文件名来创建一个输入流，如<1>
//也可以用一个文件对象来创建输入流，如<2>
class FileDealClass {
    //FileInputStream流，用于从文件读取数据，他的对象可以用new创建
    static void FileInputTest() throws IOException {
        //<1>
        //FileInputStream fis = new FileInputStream("D:/java/test.txt");
        //<2>
        File f = new File("D:/java/test.txt");
        FileInputStream fis2 = new FileInputStream(f);
        byte[] cache = new byte[1024];
        int c = fis2.read(cache, 0, cache.length);
        if (c == -1) {
            System.out.println(Arrays.toString(cache));
        }
        fis2.close();
    }

    //FileOutputStream
    //该类用来创建一个文件，并且向文件中读取数据
    //如果该流在打开时候没有这个文件，将会创建该文件
    //创建对象如上
    static void FileOutputTest() throws IOException {
        File f = new File("D:/java/test.txt");
        FileOutputStream fos = new FileOutputStream(f);
        byte[] cache = new byte[8];
        for (byte con : cache) {
            con = 'A';
        }
        fos.write(cache);
    }

    //读写文件
    static void myFileOperationTest() throws IOException {
        //将这个字符写到文件中去
        byte[] b_write = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
        File f = new File("D:/java/test.txt");
        FileOutputStream fos = new FileOutputStream(f);
        FileInputStream fis = new FileInputStream(f);
        fos.write(b_write);
        byte[] b_read = new byte[b_write.length];
        fis.read(b_read, 0, b_write.length);
        for (byte b : b_read) {
            System.out.print((char) b);
        }
        fos.close();
        fis.close();
    }
}

//java文件
class FileOperationClass {
    //创建文件和删除文件,mkdir/mkdirs和delete
    //mkdir创建一个文件，mkdirs创建文件以及子目录
    //delete不支持删除子文件，所以删除时确认没有子文件夹

    static void FileOperationTest() throws IOException {
        String fileName = "D:/java/bin";
        File f = new File(fileName);
        boolean bool = f.mkdirs();
        if (bool) {
            System.out.println("创建成功");
        } else {
            System.out.println("创建失败");
        }
        boolean bool2 = f.delete();
        if (bool) {
            System.out.println("删除成功");
        } else {
            System.out.println("删除失败");
        }
    }


    //读取文件
    //isDirectory判断是否为目录
    //list()返回目录下的文件夹
    static void fileList() {
        StringBuffer fileName = new StringBuffer("D:/java");
        File f = new File(fileName.toString());
        if (f.isDirectory()) {
            String[] files = f.list();
            if (files == null)
                return;
            for (String file_name : files) {
                System.out.println(file_name);
            }
        }
    }
    //Todo 利用递归删除文件和其子文件夹

}

/*
InputStream:字节输入流的超类,抽象类
outputStream :字节输入流的超类，抽象类
 */

class FileIoClass {
    static String fileName = "D:\\java\\dddd.txt";
    static String sourceFile = "D:\\java\\sourceFile.txt";
    static String targetFile = "D:\\java\\targetFile.txt";
    /*
    三步
    1.创建字节输出流对象
    2.调用字节输出流写数据
    3.释放资源
     */

    /**
     * 字节流写入
     */
    static void FileWriteTest() throws IOException {
        //FileOutputStream 文件输出流用于数据写入File
        /*
        做了三件事情
        A：调用系统功能创建了文件
        B：创建了字节输出流对象
        C：让字节输出流对象指向创建好的文件
         */

//        FileOutputStream fos = new FileOutputStream(fileName);
        //追加写入,写数据得时候默认写入末尾
        FileOutputStream fos = new FileOutputStream(fileName, true);
        try {
            File file = new File(fileName);
            //a,b,c
            byte[] fosByte = {97, 98, 99};
            byte[] fosByte2 = "fuzhiyu".getBytes();
            //其他构造方法
//        FileOutputStream fos2 = new FileOutputStream(file);
//        fos2.close();
            //底层得动作
            // FileOutputStream fos = new FileOutputStream(new File(fileName));
            //void write(int b) 将指定得字节写入此文件
            //@overload
            //write(int b)
            //write(byte[] b)
            //write(byte[] ,int off ,int len),将len字节从指定得字节数组开始，从偏移量off开始写入此文件输出流，一次血一个字节数组得部分数据
            //所有和IO相关得类都需要释放对应得资源
            //写入得是ask码，自动转码
            //写入a
            fos.write(97);
            //写入abc
            fos.write(fosByte);
            //写入bc
            fos.write(fosByte, 1, 2);
            //写入fuzhiyu
            fos.write(fosByte2);
            fos.write(fosByte2, 0, fosByte2.length);
            //1.字节流换行
            //注意，不同得系统换行符号是不一样得
            for (int i = 0; i < 10; i++) {
                fos.write(("hello" + i).getBytes());
                fos.write("\n".getBytes());
            }
        } catch (IOException e) {
            throw new IOException(e);
        } finally {
            //为了程序得健壮性，需要队fos进行空指针判断
            if (fos != null) {
                fos.close();
            }
        }

    }

    /**
     * 字节流读取
     */
    static void FileReadTest() throws IOException {
        /*
        1.创建字节输入流对象
        2.调用字节输入流对象的读数据方法
        3.释放资源
         */
        FileInputStream fis = new FileInputStream(fileName);
        try {
//            byte[] bys = new byte[20];
//            int len  =  fis.read(bys);
//            //换行符也要占一个字节
//            System.out.println(len);
//            System.out.println(new String(bys));
            //代码优化
            byte[] bys2 = new byte[1024];
            int len = 0;
            while ((len = fis.read(bys2)) != -1) {
                System.out.println(new String(bys2, 0, len));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (fis != null) {
                fis.close();
            }
        }
    }

    /**
     * 字节缓冲流
     * BufferOutputStream
     * BufferedInputStream
     * 该类实现缓冲输出流，通过设置设这样的输出流，应用程序可以向底层输出流写入字节，而不必为每个字节调用底层
     */
    static void byteBuffer() throws IOException {
        /*
        构造方法
        BufferedOutputStream(OutputStream out)
        BufferedInputStream(InputStream in)
        //为什么构造方法只需要字节流不需要具体文件呢
        以为字节缓冲流仅仅提供缓冲区，而真正的读写数据还是依靠基本的字节流对象操作
         */
        FileOutputStream fos = new FileOutputStream(fileName);
        BufferedOutputStream bFos = new BufferedOutputStream(fos);
        BufferedInputStream bFis = new BufferedInputStream(new FileInputStream(sourceFile));
//        bFos.write(12);
        try{

            byte[] bys = new byte[1024];
            int len;
            while ((len=bFis.read(bys))!=-1){
                System.out.println(new String(bys,0,len));
            }
        } catch (IOException e) {
            throw new IOException(e);
        } finally {
            bFos.close();
            bFis.close();
        }
        //写数据
    }
    /**
     * 字符流
     */
    static void byteStream() throws IOException {
        BufferedInputStream bufIn  = new BufferedInputStream(new FileInputStream(new File("D:\\java\\test.txt")));
        try{
            int byt;
            while ((byt = bufIn.read())!=-1){
                System.out.println((char)byt);
            }
        } catch (IOException e) {
            throw new IOException(e);
        }finally {
            if(bufIn!=null){
                bufIn.close();
            }
        }
    }
    /**
     * 案例，复制一个文件到另一个文件
     */
    static void copyAndPaste() throws IOException {
        byte[] bytes = new byte[1024];
        FileInputStream fileInputStream = new FileInputStream(sourceFile);
        FileOutputStream fileOutputStream = new FileOutputStream(targetFile,true);
        try{
            int len;
            while((len = fileInputStream.read(bytes))!=-1){
                System.out.println(new String(bytes,0,len));
                fileOutputStream.write(bytes,0,len);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(fileOutputStream!=null){
                fileInputStream.close();
            }
            if(fileOutputStream!=null){
                fileOutputStream.close();
            }
        }
    }
    /**
     * 案例2复制视频
     */
    static void copyVideoManager() throws IOException {
        long startTime = System.currentTimeMillis();
        try{
            copyVideo3();
        } catch (IOException e) {
            throw new IOException(e);
        }

        long endTime = System.currentTimeMillis();
        System.out.println("共耗时:"+(endTime - startTime)+"ms");

    }
    //基本字节流一次读一个字节
    static void copyVideo() throws FileNotFoundException {
        String sourceName = "D:\\test\\file1\\myVideo.mp4";
        String targetName = "D:\\test\\file2\\myVideoCopy.mp4";
        FileInputStream fis = new FileInputStream(sourceName);
        FileOutputStream fos = new FileOutputStream(targetName);
        int by;
        try{
            while((by =fis.read() )!=-1){
                fos.write(by);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //基本字节流一次读一个字节
    static void copyVideo2() throws FileNotFoundException {
        byte[] bys = new byte[1024];
        String sourceName = "D:\\test\\file1\\myVideo.mp4";
        String targetName = "D:\\test\\file2\\myVideoCopy2.mp4";
        FileInputStream fis = new FileInputStream(sourceName);
        FileOutputStream fos = new FileOutputStream(targetName);
        int by;
        try{
            while((by =fis.read(bys) )!=-1){
                fos.write(bys,0,by);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //基本字节缓冲流实现copy
    static void copyVideo3() throws FileNotFoundException {
        byte[] bys = new byte[1024];
        String sourceName = "D:\\test\\file1\\myVideo.mp4";
        String targetName = "D:\\test\\file2\\myVideoCopy3.mp4";
        FileInputStream fis = new FileInputStream(sourceName);
        FileOutputStream fos = new FileOutputStream(targetName);
        BufferedInputStream bFis = new BufferedInputStream(fis);
        BufferedOutputStream bFos = new BufferedOutputStream(fos);
        int by;
        try{
            while((by =bFis.read(bys) )!=-1){
                bFos.write(bys,0,by);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

//案例递归遍历文件夹
class FileManagerDemo {
    static void FileManager(String fileName) {
        File file = new File(fileName);
        if (file.exists()) {
            File[] fileList = file.listFiles();
            for (File file1 : fileList) {
                if (file1.isFile()) {
                    System.out.println("   " + file1.getName());
                } else {
                    System.out.println(file1.getName());
                    FileManagerDemo.FileManager(file1.getAbsolutePath());
                }
            }
        }

    }
}
